package cn.ibizlab.odoo.core.util.aspect;

import cn.ibizlab.odoo.core.util.annotation.DEPredefinedField;
import cn.ibizlab.odoo.core.util.enums.DEPredefinedFieldFillMode;
import cn.ibizlab.odoo.core.util.enums.DEPredefinedFieldType;
import cn.ibizlab.odoo.core.util.helper.DEFieldCacheMap;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 实体预置属性切面：用于填充实体预置属性
 */
@Aspect
@Order(0)
@Component
public class DEPredefinedFieldAspect
{
    /**
     * 新建数据切入点
     * @param point
     * @throws Exception
     */
    @Before(value = "execution(* cn.ibizlab.odoo.core.*.service.*.create(..))")
    public void BeforeCreate(JoinPoint point) throws Exception {
        ExecuteAspect(point, DEPredefinedFieldFillMode.INSERT);
    }

    /**
     * 更新数据切入点
     * @param point
     * @throws Exception
     */
    @Before(value = "execution(* cn.ibizlab.odoo.core.*.service.*.update(..))")
    public void BeforeUpdate(JoinPoint point) throws Exception {
        ExecuteAspect(point, DEPredefinedFieldFillMode.UPDATE);
    }

    /**
     * 执行切面逻辑
     * @param joinPoint  切入点
     * @param serviceFillMode  填充模式
     * @return
     */
    public Object ExecuteAspect(JoinPoint joinPoint, DEPredefinedFieldFillMode serviceFillMode) throws Exception {
        Object[] args = joinPoint.getArgs();
        if (args.length > 0) {
            Object obj = args[0];
            String className=obj.getClass().getName();
            //获取当前po对象中的属性
            DEFieldCacheMap.getFieldMap(className);
            //从属性列表中过滤出预置属性
            Map<Field, DEPredefinedField> preFields = this.SearchPreField(className);
            //填充预置属性
            fillPreField(obj, serviceFillMode, preFields);
            return true;
        }
        return true;
    }

    /**
     *获取系统预置属性
     * @param className po对象类名
     * @return
     */
    private Map <Field, DEPredefinedField> SearchPreField(String className){

        List<Field> fields =  DEFieldCacheMap.getFields(className);
        Map <Field, DEPredefinedField> preFieldMap =new HashMap<>();
        for(Field field:fields){
            DEPredefinedField prefield=field.getAnnotation(DEPredefinedField.class);
            if(!ObjectUtils.isEmpty(prefield)) {
                preFieldMap.put(field,prefield);
            }
        }
        return preFieldMap;
    }

    /**
     * 填充系统预置属性
     * @param et   当前实体对象
     * @param serviceFillMode  操作类型 insert or update
     */
    private void fillPreField(Object et, DEPredefinedFieldFillMode serviceFillMode, Map<Field, DEPredefinedField> preFields) throws Exception {
        if(preFields.size()==0)
            return ;

        for (Map.Entry<Field, DEPredefinedField> entry : preFields.entrySet()) {

            //获取预置属性
            Field preField=entry.getKey();
            String filename=preField.getName();
            //获取预置属性注解
            DEPredefinedField fieldAnnotation=entry.getValue();
            //获取预置属性类型
            DEPredefinedFieldType preFieldType=fieldAnnotation.preType();
            //获取预置属性填充模式
            DEPredefinedFieldFillMode fieldFillMode=fieldAnnotation.fill();
            //获取预置属性的get、set方法及字段值
            PropertyDescriptor field = new PropertyDescriptor(filename, et.getClass());
            Method fieldSetMethod = field.getWriteMethod();
            Method fieldGetMethod = field.getReadMethod();
            Object fieldValue = fieldGetMethod.invoke(et);

            //为预置属性进行赋值
            if(org.springframework.util.StringUtils.isEmpty(fieldValue)||preFieldType== DEPredefinedFieldType.UPDATEDATE||
                    preFieldType== DEPredefinedFieldType.UPDATEMAN||preFieldType== DEPredefinedFieldType.UPDATEMANNAME){

                if(serviceFillMode==fieldFillMode||fieldFillMode== serviceFillMode.INSERT_UPDATE){
                    switch(preFieldType){//根据注解给预置属性填充值
                        case CREATEMAN:
                            break;
                        case CREATEMANNAME:
                            break;
                        case UPDATEMAN:
                            break;
                        case UPDATEMANNAME:
                            break;
                        case CREATEDATE:
                            fieldSetMethod.invoke(et,new Timestamp(new Date().getTime()));
                            break;
                        case UPDATEDATE:
                            fieldSetMethod.invoke(et,new Timestamp(new Date().getTime()));
                        case ORGID:
                            break;
                        case ORGNAME:
                            break;
                        case ORGSECTORID:
                            break;
                        case ORGSECTORNAME:
                            break;
                        case LOGICVALID:
                            break;
                    }
                }
            }
        }
    }
}
